package com.example.demo.database.services.base;

import com.example.demo.database.services.system.LoadClassService;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

public abstract class BaseKernel {


    public String scanPath() {
        return "";
    }

    public abstract void sqlConnectorBuild();

    public abstract Column sqlConnectorGetLast();

    public abstract List<String> sqlConnectorGetExistsList();

    public abstract List<String> sqlConnectorGetBatchList(int batch);

    public abstract SqlCompiler sqlConnectorGetCompiler();

    public abstract void upFinish(String name, int batch);

    public abstract void downFinish(String name, int batch);

    public class Column {
        public String id;
        public String migration;
        public int batch;
    }

    private void init() {
        //初始化创建了migrations表，并做好数据库连接
        sqlConnectorBuild();
    }

    /**
     * 是否使用严格模式（即无视顺序，精确匹配每个不存在的迁移）
     *
     * @return
     */
    public boolean strictUpMode() {
        return false;
    }

    private List<Migrator> initClass() throws IOException {
        //加载所有class的名字
        List<String> list = LoadClassService.loadClasses(scanPath());
        //筛选出是迁移的class
        List<Migrator> migratorList = new ArrayList<>();
        for (String s : list) {
            try {
                //加载这个类
                Class clazz = Class.forName(s);
                Object o = clazz.getDeclaredConstructor().newInstance();
                if (o instanceof Migrator) {
                    //如果是迁移，则加入到迁移的列表中
                    migratorList.add((Migrator) o);
                }
            } catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException |
                     InstantiationException | IllegalAccessException e) {
                //有错不管
            }
        }
        //基于名字对列进行排序
        migratorList.sort((o1, o2) -> o1.getMigration().compareToIgnoreCase(o2.getMigration()));
        return migratorList;
    }

    private void upDoing() {
        //载入下面所有的类
        try {
            //获得所有类
            List<Migrator> migratorList = initClass();
            //记录需要增加的类
            List<Migrator> appendMigratorList = new ArrayList<>();
            //获得最后一个
            Column column = sqlConnectorGetLast();
            int batch;
            //如果不是空的，则重新计算migratorList要生成的数量
            if (column != null) {
                //新的一轮生成
                batch = column.batch + 1;
                if (strictUpMode()) {
                    //如果是严格模式，则按照获得列表和存在列表进行双比对
                    List<String> existsList = sqlConnectorGetExistsList();
                    for (Migrator migrator : migratorList) {
                        boolean exist = false;
                        for (String name : existsList) {
                            //如果名字匹配
                            if (migrator.getMigration().equals(name)) {
                                exist = true;
                                break;
                            }
                        }
                        if (!exist) {
                            //如果整个for循环走完，都不是true，说明没加过，需要加入
                            appendMigratorList.add(migrator);
                        }
                    }
                } else {
                    //所有继承的对象都拿来比较一次
                    boolean last = false;
                    for (Migrator migrator : migratorList) {
                        if (last) {
                            //如果是真，说明已经超过组后一个，则把这些都加到要加进去的
                            appendMigratorList.add(migrator);
                        } else {
                            //否则判断是否到最后一个
                            if (migrator.getMigration().equals(column.migration)) {
                                last = true;
                            }
                        }
                    }
                }
            } else {
                //不是空的就是全部都处理
                batch = 1;
                appendMigratorList = migratorList;
            }
            for (Migrator migrator : appendMigratorList) {
                //然后对所有需要增加的migrator，执行up方法
                migrator.up(sqlConnectorGetCompiler());
                //执行成功后写入到数据库中
                upFinish(migrator.getMigration(), batch);
            }
            System.out.println("ok");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void downDoing() {
        //载入下面所有的类
        try {
            //获得所有类
            List<Migrator> migratorList = initClass();
            //获得最后一个
            Column column = sqlConnectorGetLast();
            List<Migrator> removeMigratorList = new ArrayList<>();
            //如果不是空的，则重新计算migratorList要生成的数量
            if (column != null) {
                //获得要删掉的
                List<String> removeName = sqlConnectorGetBatchList(column.batch);
                for (String name : removeName) {
                    //判断名字一样就加入
                    for (Migrator migrator : migratorList) {
                        if (migrator.getMigration().equals(name)) {
                            removeMigratorList.add(migrator);
                        }
                    }
                }
                for (Migrator migrator : removeMigratorList) {
                    //然后对所有需要增加的migrator，执行up方法
                    migrator.down(sqlConnectorGetCompiler());
                    //执行成功后写入到数据库中
                    downFinish(migrator.getMigration(), column.batch);
                }
            }
            System.out.println("ok");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void up() {
        init();
        upDoing();
    }

    public void down() {
        init();
        downDoing();
    }
}
